package AircraftDesignKg.server;

import AircraftDesignKg.entity.DeepSeekRequest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;

/**
 * AI服务
 */
@Service
public class AiCommandService extends AbstractService<String, DeepSeekRequest> {
    // TODO 杨佳乐
    // 说明：该服务需要将文件输入包装为可发送给 DeepSeek 的格式
    // 可前往 ServiceImpl 查看用法
    // prompt 直接添加即可, 不需要修改

    // 自定义Prompt，根据实际需求修改
    private static final String PROMPT =
            """
            请根据以下飞机设计文档内容，提取关键信息并以 标准 JSON 格式 返回以下两类信息：
            节点列表 nodes：包含唯一标识 id、标签 labels 和属性 properties
            关系列表 relationships：包含关系类型 type、起始节点 from、目标节点 to 和可选属性 properties
            每个节点必须有唯一的 id 字段，用于关联关系。
            节点可以有多个标签（如 "Aircraft"、"Manufacturer"）。
            属性字段支持字符串、数字、布尔值等基本类型。
            关系必须指定 type、from 和 to。
            不要添加任何额外字段或说明，只返回 JSON 内容。
            示例输出格式如下：\
            {
              "nodes": [
                {
                  "id": "A1",
                  "labels": ["Aircraft", "FixedWing"],
                  "properties": {
                    "name": "Boeing 787",
                    "manufacturer": "Boeing",
                    "year": 2011,
                    "isMilitary": false
                  }
                },
                {
                  "id": "B1",
                  "labels": ["Manufacturer"],
                  "properties": {
                    "name": "Boeing",
                    "headquarters": "USA"
                  }
                }
              ],
              "relationships": [
                {
                  "type": "DESIGNED_BY",
                  "from": "A1",
                  "to": "B1",
                  "properties": {
                    "since": 2011
                  }
                }
              ]
            }\
            注意项:
                节点和变量命名: 只能使用字母、数字、下划线 _，不能以数字开头；避免使用保留关键字（如 a, b, type, id）
                节点标签: 标签名应为大驼峰格式（如 :Person, :Company），支持多个标签
                属性名: 属性名推荐小驼峰格式（如 name, birthYear）
                字符串引号: 使用单引号 'value' 或双引号 "value" 都可以，但要统一
                数值类型: 不加引号表示数值型，如 age: 30 是整数，score: 98.5 是浮点数
                布尔值: 使用 true / false，不要加引号
                空值处理: 使用 null 表示空值，不要用 "" 或 0 替代
            时间处理方式：将日期统一格式化为年份整数（如 2011）或 ISO 格式字符串（如 "2011-05-01"）。
            枚举字段控制：如 type 字段只能是预定义的关系类型，如 DESIGNED_BY, USED_IN, PART_OF 等。
            避免嵌套结构：AI 不应输出嵌套对象或数组，所有数据都应展平为键值对。\
            请确保生成的知识图谱结构化数据（JSON 格式）可转换为 Neo4j 的 Cypher 查询语句并执行入库。
            """;

    private static final Logger log = LogManager.getLogger(AiCommandService.class);

    @Value("${deepseek.api.model}")
    private String model;

    /**
     * 服务对外唯一接口方法
     * @param docsContent 文件输入(已转为字符串)
     * @return DeepSeekRequest
     */
    public DeepSeekRequest doProcess(String docsContent) throws Exception {
        // 异常向上抛, 不要在本级吞掉, 但需要打日志
        try {
            // 构建请求体
            DeepSeekRequest request = new DeepSeekRequest();
            request.setModel(model);

            // 队列化, 添加消息
            request.setMessages(List.of(
                    new DeepSeekRequest.Message("user", buildInputContent(docsContent)),
                    // prompt 直接添加即可, 不需要修改
                    new DeepSeekRequest.Message("system", PROMPT)
            ));

            // 设置其他可选参数
            request.setTemperature(0.7); // 温度参数，控制输出的随机性，值越高越随机，范围 0 - 2.0
            request.setMax_tokens(5000);   // 最大返回的 token 数
            request.setTop_p(0.8);        // 核心采样比例，范围 0 - 1.0
            request.setFrequency_penalty(0.0); // 频率惩罚系数，范围 -2.0 到 2.0
            request.setPresence_penalty(0.0);  // 存在惩罚系数，范围 -2.0 到 2.0

            // 响应格式控制，这里设置为JSON格式
            DeepSeekRequest.ResponseFormat responseFormat = new DeepSeekRequest.ResponseFormat();
            responseFormat.setType("json_object");
            request.setResponse_format(responseFormat);

            // 不返回概率信息
            request.setLogprobs(false);

            return request;

        } catch (Exception e) {
            log.error("[error] DeepSeek请求体构建异常 {}", e.getMessage());
            throw e;
        }
    }

    /**
     * 生成用户输入内容
     * @param docsContent 文件输入(已转为字符串)
     * @return 构建好的用户输入内容
     */
    public String buildInputContent(String docsContent) {
        // 这里可以根据实际需求对文档内容进行处理，例如添加一些前缀或后缀
        // 目前简单地直接返回文档内容
        return docsContent;
    }
}